using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DataRegistry<DataType>
{
    /// <summary>
    /// Summary of the data.
    /// </summary>
    private Dictionary<string, DataType> _dataSummary;
    /// <summary>
    /// The postions of a data to locate.
    /// </summary>
    private Dictionary<string, RegistryType[]> _positions;
    /// <summary>
    /// Each register have a key list.
    /// </summary>
    private HashSet<string>[] _register;
    public DataRegistry()
    {
        _dataSummary = new Dictionary<string, DataType>();
        _positions = new Dictionary<string, RegistryType[]>();
        _register = new HashSet<string>[(int)RegistryType.ENUM_END];
    }

    public DataType this[string key] { get => _dataSummary[key]; }

    public bool ContainsKey(string key) { return _dataSummary.ContainsKey(key); }

    public void Register(string key, DataType data, params RegistryType[] registryTags)
    {
        if (_dataSummary.ContainsKey(key)) return;//do not register the value with the same key
        _dataSummary.Add(key, data);//the new one is in the summary of the data now
        if (registryTags.Length == 0) return;//has no specific destination
        foreach (var item in registryTags) _register[(int)item].Add(key);//register in the destination
        _positions.Add(key, registryTags);//register the positions
    }

    public void Unregister(string key)
    {
        if (!_dataSummary.ContainsKey(key)) return;
        _dataSummary.Remove(key);
        if (!_positions.ContainsKey(key)) return;//has no specific destination
        foreach (var item in _positions[key]) _register[(int)item].Remove(key);//remove target from the destination
        _positions.Remove(key);//remove the positions
    }

    public DataType[] DataWithTag(RegistryType registryTag)
    {
        if (registryTag != RegistryType.ENUM_END)
        {
            DataType[] datas = new DataType[_register[(int)registryTag].Count];
            int i = 0;
            foreach (var item in _register[(int)registryTag])
            {
                datas[i++] = _dataSummary[item];
            }
            return datas;
        }
        else return null;
    }

    public DataType[] DataWithoutTag(RegistryType registryTag)
    {
        if (registryTag != RegistryType.ENUM_END)
        {
            DataType[] datas = new DataType[_dataSummary.Count - _register[(int)registryTag].Count];
            int i = 0;
            foreach (var item in _dataSummary.Keys)
            {
                if (!_register[(int)registryTag].Contains(item))//ont in the target hashset
                {
                    datas[i++] = _dataSummary[item];
                }
            }
            return datas;
        }
        else//all datas
        {
            DataType[] datas = new DataType[_dataSummary.Count];
            int i = 0;
            foreach (var item in _dataSummary.Keys)
            {
                datas[i++] = _dataSummary[item];
            }
            return datas;
        }
    }
}